home *** CD-ROM | disk | FTP | other *** search
- #include <windows.h>
- #include "resource.h"
-
- LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM );
-
- // アプリケーションの名前を登録
- char szAppName[] = "passwin";
-
- // 標準の argc, argv を利用可能にするための宣言
- #define argc __argc
- #define argv __argv
- extern int argc;
- extern char **argv;
-
- HWND hwnd;
- HWND hDesktopWindow;
- HWND hProgmanWindow;
- HANDLE hInstance;
- RECT rectClientReserved;
- BOOL fShown = FALSE;
- UINT ArraySize = 128;
-
- typedef struct WINStag
- {
- HWND hwnd;
- RECT rc;
- } WINS;
- WINS* hWindowsArray;
-
- NOTIFYICONDATA nid;
-
- UINT NumberOfWindows;
-
- int RestoreInt( char* section, char* key, int def );
- void ReserveInt( char* section, char* key, int i );
- void ModifyWindowRgn( void );
- HWND SetUnderWindowThrough( int n );
- BOOL CALLBACK EnumWindowsProc( HWND hEnumWnd, LPARAM lParam );
- void FreeWindowsArray( void );
- void ChangeWindowRgn( WINS );
- void ResetAllWindows( void );
-
-
- // プログラムのエントリポイント
- int PASCAL WinMain( HANDLE hInstance, HANDLE hPrevInstance,
- LPSTR lpszCmdParam, int nCmdShow )
- {
- MSG msg;
- WNDCLASS wndclass;
-
- int xPos = RestoreInt( "Settings", "xPos", 0 );
- int yPos = RestoreInt( "Settings", "yPos", 0 );
- int cWidth = RestoreInt( "Settings", "Width", 280 );
- int cHeight = RestoreInt( "Settings", "Height", 100 );
-
-
- // 重複起動を防ぐ
- if( FindWindow( "PASSWIN", szAppName ) != NULL ) return FALSE;
-
- hDesktopWindow = GetDesktopWindow();
- hProgmanWindow = FindWindow( "Progman", NULL );
- // wndclass の定義
- wndclass.style = 0;
- wndclass.lpfnWndProc = WndProc;
- wndclass.cbClsExtra = 0;
- wndclass.cbWndExtra = 0;
- wndclass.hInstance = hInstance;
- wndclass.hIcon = LoadIcon( hInstance, IDI_APPLICATION );
- wndclass.hCursor = LoadCursor( NULL, IDC_ARROW );
- wndclass.hbrBackground = GetStockObject( WHITE_BRUSH );
- wndclass.lpszMenuName = NULL;
- wndclass.lpszClassName = szAppName;
- // wndclass を登録する
- RegisterClass( &wndclass );
-
- // ウィンドウを作成する
- hwnd = CreateWindowEx( WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE,
- szAppName, // window class name
- "PASS THROUGH WINDOW", // window caption
- WS_OVERLAPPEDWINDOW, // window style
- xPos, // initial x position
- yPos, // initial y position
- cWidth, // initial x size
- cHeight, // initial y size
- NULL, // parent window handle
- NULL, // window menu handle
- hInstance, // program instance handle
- NULL ); // creation parameters
-
- nid.cbSize = sizeof(NOTIFYICONDATA);
- nid.hWnd = hwnd;
- nid.uID = 1112;
- nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
- nid.uCallbackMessage = 1112;
- nid.hIcon = LoadIcon( hInstance, MAKEINTRESOURCE(IDI_ICON) );
- strcpy( nid.szTip, "Pass through Window" );
-
- Shell_NotifyIcon( NIM_ADD, &nid );
-
- ModifyWindowRgn();
- hWindowsArray = (WINS*)malloc( ArraySize*sizeof(WINS) );
-
- ShowWindow( hwnd, SW_HIDE );
- ResetAllWindows();
- fShown = FALSE;
- UpdateWindow( hwnd );
-
-
- while( GetMessage( &msg, NULL, 0, 0 ) )
- {
- TranslateMessage( &msg );
- DispatchMessage( &msg );
- }
- Shell_NotifyIcon( NIM_DELETE, &nid );
- return msg.wParam;
- }
-
- LRESULT CALLBACK WndProc( HWND hwnd, UINT message, UINT wParam, LONG lParam )
- {
- static POINT pt;
- static UINT nTimer;
- static HDC hDC;
- static char szCursorPos[128];
- static RECT rc;
- static PAINTSTRUCT ps;
- static int xPos, yPos;
- static int cWidth, cHeight;
-
- switch( message )
- {
- case WM_CREATE:
- hInstance = ( (LPCREATESTRUCT) lParam )->hInstance;
- nTimer = SetTimer( hwnd, 0, 100, NULL );
- return 0;
-
- case WM_SIZE:
- ResetAllWindows();
- ModifyWindowRgn();
- SetUnderWindowThrough( 0 );
- return 0;
-
- case WM_MOVE:
- ResetAllWindows();
- SetUnderWindowThrough( 0 );
- break;
-
- case 1112:
- switch( lParam )
- {
- case 0x201: // LBUTTONDOWN
- // if( fShown == TRUE ) break;
- ShowWindow( hwnd, SW_SHOWNORMAL );
- // ResetAllWindows();
- ModifyWindowRgn();
- SetUnderWindowThrough( 0 );
- fShown = TRUE;
- break;
- case 0x204: // RBUTTONDOWN
- // if( fShown == FALSE ) break;
- ShowWindow( hwnd, SW_HIDE );
- ResetAllWindows();
- fShown = FALSE;
- break;
- }
- break;
-
- case WM_ACTIVATE:
- ResetAllWindows();
- switch( LOWORD(wParam) )
- {
- case WA_ACTIVE:
- case WA_CLICKACTIVE:
- if( fShown == FALSE ) break;
- ModifyWindowRgn();
- SetUnderWindowThrough( 0 );
- break;
- default:
- /* I took a misstake such that it is good
- to let restore pass-throughing the windows normal
- when this is going to nonactive.
- But in future, I may notice a good way, so I preserve
- a little code. */
- if( fShown == FALSE ) break;
- ModifyWindowRgn();
- SetUnderWindowThrough( 0 );
- if( IsIconic( hwnd ) )
- {
- ResetAllWindows();
- }
- break;
- }
- break;
-
- case WM_DESTROY:
- ResetAllWindows();
- FreeWindowsArray();
- GetWindowRect( hwnd, &rc );
- ReserveInt( "Settings", "xPos", rc.left );
- ReserveInt( "Settings", "yPos", rc.top );
- ReserveInt( "Settings", "Width", rc.right - rc.left );
- ReserveInt( "Settings", "Height", rc.bottom - rc.top );
- PostQuitMessage( 0 );
- return 0;
- }
- return DefWindowProc( hwnd, message, wParam, lParam );
- }
-
- int RestoreInt( char* section, char* key, int def )
- {
- /* レジストリから整数値を復元
- section: セクション
- key: キー
- def: デフォルト整数値
- e.g. i = RestoreInt( "FOO", "BAR", 10 );
- FOOセクションのBARキーの内容をiに代入。もし値がなければ10 */
- HKEY hKey;
- char szKey[256];
- int i;
- int size = sizeof(int);
- LONG err;
- wsprintf( szKey, "Software\\OTOBE\\PASSWIN\\%s", section );
- if( RegOpenKeyEx( HKEY_CURRENT_USER, szKey,
- 0, KEY_READ, &hKey ) != ERROR_SUCCESS )
- {
- return def;
- }
- err = RegQueryValueEx( hKey, key, 0, NULL, (LPBYTE)&i, (LPDWORD)&size );
- if( err != ERROR_SUCCESS )
- {
- return def;
- }
- RegCloseKey( hKey );
- return (int)i;
- }
-
- void ReserveInt( char* section, char* key, int i )
- {
- /* レジストリに整数値を保管
- section: セクション
- key: キー
- sz: 保管整数値
- e.g. ReserveInt( "FOO", "BAR", 10 );
- FOO セクションの下の BAR エントリに10という値を保管。*/
- HKEY hKey;
- DWORD dwDisposition;
- char szKey[256];
- wsprintf( szKey, "Software\\OTOBE\\PASSWIN\\%s", section );
- if( RegCreateKeyEx( HKEY_CURRENT_USER, szKey,
- 0, "", REG_OPTION_NON_VOLATILE, KEY_WRITE,
- NULL, &hKey, &dwDisposition ) != ERROR_SUCCESS )
- {
- MessageBox( NULL, "Error in RegCreateKey", NULL, MB_OK );
- return;
- }
- RegSetValueEx( hKey, key, 0, REG_DWORD, (BYTE *)&i, sizeof(int) );
- RegCloseKey( hKey );
- }
-
- void ModifyWindowRgn( void )
- {
- RECT rectWindow, rectClient;
- HRGN hrgnWindow, hrgnClient;
- POINT pt;
- int cx, cy;
-
- /* Now, we want to create a region that contains the window's
- components without client area.
- Because we want to create such a region, we want to use
- CreateRectRgn(Indirect) Function.
- After we create two regions, the window region and the
- client region, we will create the region that are the
- difference of them.
- We have already got the two rectangles. But one is by
- screen coordinate, another is by client coordinate.
- First, we translate client coordinate to screen one.
- Because the left and top coordinates of client area
- by client coordinate are always 0. We set pt struct
- the left-top corner of client area by screen coordinate.
- Note that the calues in rectClient structure is by
- client coordinate. We want to use this values.
- So, if we use OffsetRect Function to shift the values to
- set client area the left-top corner of screen as the whole
- window are put to the proper the corner.
- Second, we create both regions.
- Finally, We create the region as the difference of
- two regions, which we set the new region to first one. */
-
- GetWindowRect( hwnd, &rectWindow );
- GetClientRect( hwnd, &rectClient );
-
- pt.x = pt.y = 0;
- ClientToScreen( hwnd, &pt );
- cx = pt.x - rectWindow.left;
- cy = pt.y - rectWindow.top;
- OffsetRect( &rectClient, cx, cy );
-
- rectWindow.right -= rectWindow.left;
- rectWindow.bottom -= rectWindow.top;
- rectWindow.left = rectWindow.top = 0;
-
- hrgnClient = CreateRectRgnIndirect( &rectClient );
- hrgnWindow = CreateRectRgnIndirect( &rectWindow );
- CombineRgn( hrgnWindow, hrgnWindow, hrgnClient, RGN_DIFF );
- SetWindowRgn( hwnd, hrgnWindow, TRUE );
- DeleteObject( hrgnClient );
- return;
- }
-
- HWND SetUnderWindowThrough( int n )
- {
- /* This function returns the window handle that lies under this
- application, PASSWIN. */
- UINT i;
- NumberOfWindows = 0;
- EnumWindows( EnumWindowsProc, 1 );
-
- for( i = 0; i < NumberOfWindows; i++ )
- {
- ChangeWindowRgn( hWindowsArray[i] );
- }
- return NULL;
- }
-
- BOOL CALLBACK EnumWindowsProc( HWND hEnumWnd, LPARAM lParam )
- {
- /* We create hWindowsArray.
- This contains an array of window handles.
- The windows of which handles are contained in
- hWindowsArray intersects our window.
- the indexes are from 0 to NumberOfWindows-1.
- */
-
- RECT rcEnum, rcThis, rc;
-
- if( !IsWindowVisible( hEnumWnd ) )
- {
- return TRUE;
- }
- if( hEnumWnd == hwnd || hEnumWnd == hDesktopWindow || hEnumWnd == hProgmanWindow )
- {
- return TRUE;
- }
-
- GetWindowRect( hEnumWnd, &rcEnum );
- GetWindowRect( hwnd, &rcThis );
-
- if( IntersectRect( &rc, &rcThis, &rcEnum ) == 0 )
- {
- return TRUE;
- }
-
- if( NumberOfWindows >= ArraySize - 1 )
- {
- ArraySize += 16;
- hWindowsArray = (WINS*)realloc( hWindowsArray, ArraySize*sizeof(WINS) );
- }
- hWindowsArray[NumberOfWindows].hwnd = hEnumWnd;
- hWindowsArray[NumberOfWindows].rc = rc;
- NumberOfWindows++;
- return TRUE;
- }
-
- void FreeWindowsArray( void )
- {
- free( hWindowsArray );
- }
-
- void ChangeWindowRgn( WINS wins )
- {
- RECT rectTarget;
- HRGN hrgnTarget, hrgnThrough;
- /* First we get window's rectangle of target window.
- we have to move it to left-top corner of screen.
- Second, we have to move the target area.
- The amount of to move is the same of that of target window. */
- GetWindowRect( wins.hwnd, &rectTarget );
- rectTarget.right -= rectTarget.left;
- rectTarget.bottom -= rectTarget.top;
- wins.rc.left -= rectTarget.left;
- wins.rc.right -= rectTarget.left;
- wins.rc.top -= rectTarget.top;
- wins.rc.bottom -= rectTarget.top;
- rectTarget.left = rectTarget.top = 0;
-
- hrgnThrough = CreateRectRgnIndirect( &wins.rc );
- hrgnTarget = CreateRectRgnIndirect( &rectTarget );
- CombineRgn( hrgnTarget, hrgnTarget, hrgnThrough, RGN_DIFF );
- SetWindowRgn( wins.hwnd, hrgnTarget, TRUE );
- DeleteObject( hrgnThrough );
- return;
- }
-
- void ResetAllWindows( void )
- {
- UINT i;
- for( i = 0; i < NumberOfWindows; i++ )
- {
- SetWindowRgn( hWindowsArray[i].hwnd, NULL, TRUE );
- }
- }
-